using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using ALib;
using ALib.Data.IO;

namespace TradingLab.Data
{
    [Serializable]
    public class TimeData : Dictionary<string, TickerData>
    {
        public TimeData()
        {
        }

        public TimeData(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }

        public bool Contains(string tickerName, string propertyBoxName, string propertyName)
        {
            bool result = false;

            if (ContainsKey(tickerName) && this[tickerName].ContainsKey(propertyBoxName) && this[tickerName][propertyBoxName].ContainsKey(propertyName))
            {
                result = true;
            }
            return result;
        }

        public bool Contains(string tickerName, string propertyBoxName)
        {
            bool result = false;
            if (ContainsKey(tickerName) && this[tickerName].ContainsKey(propertyBoxName))
            {
                result = true;
            }
            return result;
        }

        public bool Contains(string tickerName)
        {
            bool result = false;
            if (ContainsKey(tickerName))
            {
                result = true;
            }
            return result;
        }

        public void Add(string tickerName, string propertyBoxName, string propertyName, string propertyValue)
        {
            if (!ContainsKey(tickerName))
            {
                Add(tickerName, new TickerData());
            }
            if (!this[tickerName].ContainsKey(propertyBoxName))
            {
                this[tickerName].Add(propertyBoxName, new PropertyBoxData());
            }
            if (!this[tickerName][propertyBoxName].ContainsKey(propertyName))
            {
                this[tickerName][propertyBoxName].Add(propertyName, new PropertyData());
            }
            this[tickerName][propertyBoxName][propertyName].Add(propertyValue);
        }

        public void Add(string tickerName, string propertyBoxName, string propertyName)
        {
            if (!ContainsKey(tickerName))
            {
                Add(tickerName, new TickerData());
            }
            if (!this[tickerName].ContainsKey(propertyBoxName))
            {
                this[tickerName].Add(propertyBoxName, new PropertyBoxData());
            }
            if (!this[tickerName][propertyBoxName].ContainsKey(propertyName))
            {
                this[tickerName][propertyBoxName].Add(propertyName, new PropertyData());
            }
        }

        public void Add(string tickerName, string propertyBoxName)
        {
            if (!ContainsKey(tickerName))
            {
                Add(tickerName, new TickerData());
            }
            if (!this[tickerName].ContainsKey(propertyBoxName))
            {
                this[tickerName].Add(propertyBoxName, new PropertyBoxData());
            }
        }

        public void Add(string tickerName)
        {
            if (!ContainsKey(tickerName))
            {
                Add(tickerName, new TickerData());
            }
        }

        public List<string> GetTickerNames()
        {
            List<string> result = new List<string>();
            foreach (string s in Keys)
            {
                result.Add(s);
            }
            return result;
        }

        public void MergeWith(TimeData timeData)
        {
            foreach (KeyValuePair<string, TickerData> tickerName_TickerData in timeData)
            {
                if (!ContainsKey(tickerName_TickerData.Key))
                {
                    Add(tickerName_TickerData.Key,tickerName_TickerData.Value);
                }
                else
                {
                    this[tickerName_TickerData.Key].MergeWith(tickerName_TickerData.Value);
                }
            }
        }

        public static string SerializeToBase4(TimeData timeData)
        {
            byte[] bytes = ObjectIO.SerializeToBytes(timeData);
            string result = Convert.ToBase64String(bytes);
            return result;
        }

        public static TimeData DeserializeFromBase64(string base64String)
        {
            byte[] bytes = Convert.FromBase64String(base64String);
            TimeData result = ObjectIO.DeserializeFromByteArray(bytes) as TimeData;
            return result;
        }

        public string ToCalcCommand(DateTime time)
        {
            string result = "Calc"
                            + "," + time.ToString(DateTimeFormatType.Simple)
                            + "," + SerializeToBase4(this);
            return result;
        }

        public string ToCalcCommandEx(DateTime time)
        {
            string result = "Calc"
                            + "," + time.ToString(DateTimeFormatType.Simple)
                            + "," + SerializeToBase4(this);
            return result;
        }
 
        public void Add(string tickerName, double open, double high, double low, double close, double volume, double existingOpenPosition,
    int tradingPlatformTimeZoneIndex, int exchangeTimeZoneIndex, string tradingSessionString, double exchangeRate, double pointValue, double minMove, double lotSize, double commissionOnRate, double commissinPerShareInXxx, double minCommissionInXxx, double maxCommissionInXxx, double stampDutyRate, double slippagePoints)
        {
            // Add bar
            if (!double.IsNaN(open)
                && !double.IsNaN(high)
                && !double.IsNaN(low)
                && !double.IsNaN(close)
                && !double.IsNaN(volume))
            {
                string bar = string.Format("{0},{1},{2},{3},{4}", open, high, low, close, volume);
                Add(tickerName, "", "B", bar);
            }

            // Add general information.
            string tickerGeneralInfo = string.Format(@"{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13}", tradingPlatformTimeZoneIndex, exchangeTimeZoneIndex, tradingSessionString, exchangeRate, pointValue, minMove, lotSize, commissionOnRate, commissinPerShareInXxx, minCommissionInXxx, maxCommissionInXxx, stampDutyRate, slippagePoints, existingOpenPosition);
            Add(tickerName, "", "G", tickerGeneralInfo);
        }
    }
}